
const path = require('path');
let gulp = require('gulp');
let watch = require('gulp-watch');
let ProxyMiddleware = require('http-proxy-middleware');
let del = require('del')
let connect = require('gulp-connect')
let changed = require('gulp-changed');
let gulpSequence = require('gulp-sequence').use(gulp);

// 文件处理
let postcss = require('gulp-postcss');
// let postcssrc = require('postcss-load-config');
let htmlmin = require('gulp-htmlmin');
let babel = require('gulp-babel');

// 捕获异常
let plumber = require('gulp-plumber')

/**
 *
 * @param {string} fpath
 */
function resolve(fpath) {
  return path.join(__dirname, fpath);
}

function logInfo(log, name) {
  name = name || '';
  console.log(
    '┏ ' + name + ' -------------------' +
    '\n\n' +
    log +
    '\n\n┗ ----------------------------' +
    '\n'
  )
}

/**
 * 自动加载htmlminrc配置；
 */
function htmlminrc () {
  let options = {};
  try {
    options = require('./.htmlminfyrc.js');
  } catch(e) {

  }

  return options;

}


// 目录
let app = {
  srcPath: resolve('src'),
  distRoot: resolve('dist'),
  devPath: resolve('dist/dev'),
  prdPath: resolve('dist/dist')
};

let exts = {
  html: 'html,htm',
  css: 'css',
  js: 'js',
};

/**
 *
 */
function extignore(arg) {
  let type = typeof arg;
  let result;
  if (type === 'function') {
    result = arg();
  } else if (type === 'string') {
    result = arg.split(',');
  }

  return result;
}

/**
 * 生成随机端口
 */
function randomPort() {
  var port = parseInt(Math.random() * 65535)
  if (port < 5000 || port === this.port) {
    port = randomPort.call(this);
  }

  return port;
}


let ProxyConf = {
  origin: ['/v1/**', '!/v1/**.*', '!/v1/'],
  target: 'https://xxx.xxx.com',
  host: 'http://localhost:8081'
};

/**
 * 生成代理列表
 * @param {*} ProxyConf cofnig
 */
function generationOps(ProxyConf) {
  let proxyTable = [];
  let ProxyOptions = {
    changeOrigin: true,
    logLevel: 'debug',
    ignorePath: true,
    router: function (req) {
      let origin = req.originalUrl;
      let target = ProxyConf.target + origin;
      return target;
    },
    target: ProxyConf.host
  };

  proxyTable.push(ProxyMiddleware(ProxyConf.origin, ProxyOptions));
  return proxyTable;
}

let proxyTable = generationOps(ProxyConf);

//  server config
let serverConfig = {
  root: app.devPath,
  port: 8081,
  livereload: {
    port: randomPort.call(this)
  },
  // proxy
  middleware: function (options, e) {
    return proxyTable;
  }
};

/**
 *  添加错误处理
 * @param {*} src
 */
function gulpPipe(src) {
  let stream = gulp.src(src)
    .pipe(plumber())

  return stream
}

/**
 *  流完成后reload
 */
function gulpTask() {

  let arg = [].splice.call(arguments, 0);
  if (typeof arg[arg.length - 1] === 'function') {
    let cb = arg.pop();
    arg.push(function () {
      let stream = cb.call(this);
      return stream.pipe(connect.reload());
    })
  };
  return gulp.task.apply(gulp, arg);
}

// 清除文件
gulp.task('del', function () {
  try {
    return del.sync([app.distRoot])
  } catch (e) {
    console.log('删除失败');
    return gulp;
  }
});

// 处理html
gulpTask('html', function () {
  return gulpPipe(`${app.srcPath}/**/*.{${exts.html}}`)
    .pipe(changed(app.devPath))
    .pipe(htmlmin(htmlminrc()))
    // 只有被更改过的文件才会通过这里
    .pipe(gulp.dest(app.devPath));
});

// 处理css
gulpTask('css', function (e) {
  return gulpPipe([`${app.srcPath}/**/*.{css,}`])
  .pipe(changed(app.devPath))
  .pipe(postcss())
  .pipe(gulp.dest(app.devPath));
});

// 处理js
gulpTask('js', function(e) {
  return gulpPipe([`${app.srcPath}/**/*.{js,}`])
  .pipe(changed(app.devPath))
  .pipe(babel())
  .pipe(gulp.dest(app.devPath));
});

// 处理所有文件;
gulpTask('oct', function () {
  let exts = extignore('css,html,js');
  return gulpPipe([`${app.srcPath}/**/*.*`, `!${app.srcPath}/**/*.{${exts}}`])
    .pipe(changed(app.devPath))
    .pipe(gulp.dest(app.devPath))
});

// ++++++ task config ++++++
gulp.task('server', ['build', 'watcher'], function () {
  connect.server(serverConfig);
}).on('end', function (params) {

});

// 打包项目
gulp.task('build', ['del', 'dev']);

gulp.task('dev', function (cb) {
  return gulpSequence(['oct', 'css', 'html', 'js'], cb);
});

// 默认执行 server
gulp.task('default', ['server']);

// wactcher
gulp.task('watcher', function () {

  // 监听文件的变化
  let watcher = watch([app.srcPath + '/**/*.*'], {
    events: ['add', 'change'],
    read: false
  }, function (e) {
    gulp.start('dev');
  });
  //  监听删除文件
  watcher.on('unlink', onUnlink);
  // 捕获异常
  watcher.on('error', onError);
});

/**
 * 删除文件处理
 */
function onUnlink(filePath) {
  // console.log(filePath)
  let oldPath = filePath.replace(path.resolve(app.srcPath), '').split('\\').join('/');
  let newPath = oldPath;
  // 提示删除的文件
  let tips = ['unlink ::', 'oldPath == ', app.srcPath + oldPath, '  ||  newPath == ', app.devPath + newPath].join('');

  // 删除文件
  del(app.devPath + newPath).then(function (e) {
    console.log(' 删除成功 =:= ' + tips);

  }).catch(function (e) {
    logInfo(tips, '删除失败');
  });
}

/**
 * 异常处理
 */
function onError(e) {
  console.log(e);
}

// 未捕获异常
process.on('uncaughtException', function (err) {
  logInfo(err, 'process uncaughtException');
});

module.exports = gulp;
